#!/usr/bin/python
import os
import subprocess
import optparse
import time
import socket

import sys
sys.path.append('./python')
import pprint
from urlparse import urlparse
from thrift.transport import TTransport
from thrift.transport import TSocket
from thrift.transport import THttpClient
from thrift.protocol import TBinaryProtocol
import tempfile

import MyService
from ttypes import *

import hashlib

def callFunction(port, cmd, key, content, fname):
	socket = TSocket.TSocket("localhost", port)
	transport = TTransport.TBufferedTransport(socket)
	protocol = TBinaryProtocol.TBinaryProtocol(transport)
	client = MyService.Client(protocol)
	transport.open()
	pp = pprint.PrettyPrinter(indent = 2)	
	if cmd == 'addFile':
		print client.addFile(key,content, fname).replace("\n",'\n')
	elif cmd == 'delFile':
		print client.delFile(key, fname).replace("\n",'\n')
	elif cmd == 'getFile':
		print client.getFile(key, fname).replace("\n",'\n')
	elif cmd == 'getTable':
		print client.getTable(key).replace("\n",'\n')
	transport.close()


def getPort(sPort):
	port = 0
	if sPort == -1:
		sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		sock.bind(('', 0))
		port = sock.getsockname()[1]
		sock.close()
	else:
		while(port < sPort):
			sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
			sock.bind(('', 0))
			port = sock.getsockname()[1]
			sock.close()
	return port
	
def genKey(filename,m):
	#Generate key
	idgen = hashlib.sha1()
	idgen.update(filename)
	key= int(idgen.hexdigest()[32:],16) % (2**(m))
	return key

def addNodes(lnodes,m,sInt,fInt, iPort,seed, sPort):
	for n in lnodes:
		#fname = "./temp/"+str(n)
		#se = open(fname, 'w', 0)
		temp = tempfile.TemporaryFile()
		d = temp.fileno()
		port=getPort(sPort)
		command=['./node', '--m' ,str(m), '--id', str(n), '--port', str(port), '--stabilizeInterval' , str(sInt), '--introducerPort', str(iPort), '--fixInterval' , str(fInt) , '--seed' , '123']
		newpid = subprocess.Popen(command,stderr=d).pid
		print "Node with ID "+str(n)+" started at Port "+ str(port)


parser = optparse.OptionParser("usage bla bla bla")
parser.add_option('--m', dest='m', type="int")
parser.add_option('--stabilizeInterval', dest="sInterval", type="int", default=10)
parser.add_option('--startingPort', dest="sPort", type="int", default=-1)
parser.add_option('--fixInterval', dest="fInterval", default=10, type="int")
parser.add_option('--attachToNode', dest='attachToNode', default=-1, type="int")

#print parser.parse_args()
(options, args) = parser.parse_args()
m = options.m
sPort = options.sPort
sInt = options.sInterval
fInt = options.fInterval
listnerNode = options.attachToNode

millis = int(round(time.time() * 1000))
#print millis

#create introducer if attachToNode is default
iPort = listnerNode
if listnerNode== -1:
	#fname = "./temp/"+str(0)
	#se = open(fname, 'w', 0)
	temp = tempfile.TemporaryFile();
	d = temp.fileno()
	iPort=getPort(sPort)
	command=['./node', '--m' ,str(m), '--id', '0', '--port', str(iPort), '--stabilizeInterval' , str(sInt), '--fixInterval' , str(fInt) , '--seed' , str(millis)]
	newpid = subprocess.Popen(command,stderr=d).pid
	print "Introducer Started at Port ", iPort
else:
	print "Attached to Introducer at Port", iPort



#Start Accepting Commands
while (1):
	cmd = raw_input('ChordCmd?> ')
	#Check command and execute
	scmd=cmd.split()
	x=scmd[0];
	if x=='ADD_NODE':
		addNodes(scmd[1:len(scmd)],m,sInt, fInt,iPort ,millis, sPort)
	elif x=='ADD_FILE':
		data=cmd.split(None,2)
		filename=data[1]
		content=data[2]
		key= genKey(filename,m)
		#Contact attached node with <key, content, filename>
		callFunction(iPort, 'addFile', key, content, filename)
	elif x=='DEL_FILE':
		filename=scmd[1]
		key=genKey(filename,m)
		#Contact attached node with <key, filename>
		callFunction(iPort, 'delFile', key,'', filename)
	elif x=='GET_FILE':
		filename=scmd[1]
		key=genKey(filename,m)
		#Contact attached node with <key, filename>
		callFunction(iPort, 'getFile', key,'', filename)
	elif x=='GET_TABLE':
		nodeID=int(scmd[1])
		#Contact attached with <ID>
		callFunction(iPort, 'getTable', nodeID,'', '')
	else:
		print 'Invalid Command!'

